﻿

using XT.Common.Extensions;
using HbcServerProcess.Interfaces;
using IotContract.Consts;
using IotContract.Models.Clients.Hks;
using IotContract.Models.Jobs;
using IotServerService.Services.Mqtts;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

namespace HbcServerProcess.Services;
/// <summary>
/// 调度任务
/// </summary>
public class ProcessJobService:IProcessJobService
{
    private readonly IProcessDataService _processDataService;
    private readonly IEquipValidateService _equipValidateService;
    /// <summary>
    /// 入库任务
    /// </summary>
    public ConcurrentDictionary<string, ScEnterJob> ScEnterJobDic { get; set; } = new ConcurrentDictionary<string, ScEnterJob>();

    /// <summary>
    /// 堆垛机出库任务
    /// </summary>
   public ConcurrentDictionary<string, ScOutJob> ScOutJobDic { get; set; } = new ConcurrentDictionary<string, ScOutJob>();

    /// <summary>
    /// 堆垛机移库任务
    /// </summary>
   public ConcurrentDictionary<string, ScMoveJob> ScMoveJobDic { get; set; } = new ConcurrentDictionary<string, ScMoveJob>();

    /// <summary>
    /// 充放电预约任务
    /// </summary>
    public ConcurrentDictionary<string, HkWriteInstruct> HkFMTAppointDic { get; set; } = new ConcurrentDictionary<string, HkWriteInstruct>();


    public ProcessJobService(IProcessDataService processDataService,IEquipValidateService equipValidateService)
    {
        _processDataService = processDataService;
        _equipValidateService = equipValidateService;
    }
    #region 出入库任务
    /// <summary>
    /// 添加堆垛机入库任务
    /// </summary>
    /// <param name="enterJobs"></param>
    public async Task<string> AddScEnterJob(ScEnterJob job)
    {
        try
        {


            if (job.ToBay == 0 && job.ToBank == 0 && job.ToLevel == 0)
            {
                return IotMsgConst.JobError;
            }



            var tag = _processDataService.CvUnitTags.GetValueOrDefault(job.FromTagNumber);

            if (tag == null) return IotMsgConst.NoCvTagError;

            if (tag.JobNumber == 0) return IotMsgConst.CvError;

            if (tag.JobNumber != job.JobNumber) return IotMsgConst.CvError;

            // 站台是否有托盘
            if (_equipValidateService.ValidateCV(tag) == false)
            {
                return IotMsgConst.CvError;
            }

            // 如果是双叉任务
            if (job.JobID2.IsNotNullOrEmpty())
            {
                if (job.ToBay2 == 0 && job.ToBank2 == 0 && job.ToLevel2 == 0)
                {
                    return IotMsgConst.JobError;
                }
                var tag2 = _processDataService.CvUnitTags.GetValueOrDefault(job.FromTagNumber2); ;

                if (tag2.JobNumber == 0) return IotMsgConst.CvError;
                //if(tag2.W_JobNumber!=job.JobNumber2) throw new Exception("取货站台2任务号不一致")

                // 站台是否有托盘

                if (_equipValidateService.ValidateCV(tag2) == false)
                {
                    return IotMsgConst.CvError;
                }

            }

            var sctag = _processDataService.ScUnits.GetValueOrDefault(job.EquipNum);

            if (_equipValidateService.ValidateStacker(sctag) == false)
            {
                return IotMsgConst.ScError;
            }

            if (sctag.SC_State == 2 && sctag.ActionType == 1)
            {
                return IotMsgConst.ScError;
            }


            // 双叉任务
            if (job.JobID2.IsNotNullOrEmpty())
            {
                if (!ScEnterJobDic.ContainsKey($"{job.JobID}-{job.JobID2}"))
                {



                    ValidateJob(1, job.EquipNum);

                    var isAddJob = ScEnterJobDic.TryAdd($"{job.JobID}-{job.JobID2}", job);
                    
                    if (!isAddJob)
                    {
                        await Task.Delay(200);
                        ScEnterJobDic.TryAdd($"{job.JobID}-{job.JobID2}", job);
                    }
                }

            }
            else
            {
                // 单叉任务
                if (!ScEnterJobDic.ContainsKey(job.JobID))
                {

                    ValidateJob(1, job.EquipNum);

                    var isAddJob = ScEnterJobDic.TryAdd(job.JobID, job);
                    if (!isAddJob)
                    {
                        ScEnterJobDic.TryAdd(job.JobID, job);
                    }
                    
                }

            }
        }
        catch(Exception ex)
        {
            return ex.Message;
        }

        return string.Empty;

    }
    /// <summary>
    /// 验证任务
    /// </summary>
    /// <param name="type"></param>
    /// <param name="groupNumber"></param>
    private void ValidateJob(int type, int groupNumber)
    {
        int result = 0;
        // 入库
        if (type == 1)
        {
            result = ScEnterJobDic.Values.Count(x => x.EquipNum == groupNumber);
            if (result > 5)
            {
                throw new Exception(IotMsgConst.JobError1);
            }
        }
        else if (type == 2)
        {
            result = ScOutJobDic.Values.Count(x => x.EquipNum == groupNumber);
            if (result > 5)
            {
                throw new Exception(IotMsgConst.JobError1);
            }
        }
        else if (type == 3)
        {
            result = ScMoveJobDic.Values.Count(x => x.EquipNum == groupNumber);
            if (result > 5)
            {
                throw new Exception(IotMsgConst.JobError1);
            }
        }

    }

    /// <summary>
    /// 添加堆垛机移库任务
    /// </summary>
    /// <param name="job"></param>
    /// <returns></returns>
    public async Task<string> AddScMoveJob(ScMoveJob job)
    {
        if (job.ToBay == 0 && job.ToBank == 0 && job.ToLevel == 0)
        {
            return IotMsgConst.JobError;
        }

        var sctag =_processDataService.ScUnits.GetValueOrDefault(job.EquipNum);

        if (sctag.SC_State == 2 && sctag.ActionType == 3)
        {
            return IotMsgConst.ScError;
        }

        // 单叉任务
        if (!ScMoveJobDic.ContainsKey(job.JobID))
        {
            var isAddJob = ScMoveJobDic.TryAdd(job.JobID, job);
            if (!isAddJob)
            {
                ScMoveJobDic.TryAdd(job.JobID, job);
            }
        }
        return string.Empty;
    }

    /// <summary>
    /// 添加堆垛机出库任务 999是火警任务
    /// </summary>
    /// <param name="job"></param>
    /// <exception cref="Exception"></exception>
    /// <exception cref="NoControlException"></exception>
    public async Task<string> AddScOutJob(ScOutJob job)
    {
        try
        {
            if (job.FromBay == 0 && job.FromBank == 0 && job.FromLevel == 0)
            {
                return IotMsgConst.JobError;
            }
            if (job.ToStation != 999)
            {
                //var sameSc = ScEnterJobDic.Values.FirstOrDefault(x => x.Status == 1 && x.GroupNumber == job.GroupNumber);


                //var sameOutSc = ScOutJobDic.Values.FirstOrDefault(x => x.Status == 1 && x.GroupNumber == job.GroupNumber);


                //if (sameSc != null || sameOutSc != null)
                //{

                //    //相同堆垛机正在运行中，不同时启动
                //    throw new Exception("相同堆垛机正在运行中，不能同时启动");
                //}


                var tag = _processDataService.CvUnitTags.GetValueOrDefault(job.ToTagNumber);
                //站台是否有托盘
                if (tag == null)
                {
                    return IotMsgConst.NoCvTagError;
                }
                if (tag.ErrorCode > 0)
                {
                    return IotMsgConst.CvError;
                }
                if (tag.IsExistTray1)
                {
                    return IotMsgConst.CvError;
                }

                if (tag.JobNumber > 0)
                {
                    return IotMsgConst.CvError;
                }

                if (job.JobID2.IsNotNullOrEmpty())
                {
                    var tag2 = _processDataService.CvUnitTags.GetValueOrDefault(job.ToTagNumber2);

                    if (job.FromBay2 == 0 && job.FromBank2 == 0 && job.FromLevel2 == 0)
                    {
                        return IotMsgConst.JobError;
                    }

                    // 站台是否有托盘
                    if (tag2.ErrorCode > 0)
                    {
                        return IotMsgConst.CvError;
                    }
                    if (tag2.IsExistTray1)
                    {
                        return IotMsgConst.CvError;
                    }
                    if (tag2.JobNumber > 0)
                    {
                        return IotMsgConst.CvError;
                    }
                }

                var sctag = _processDataService.ScUnits.GetValueOrDefault(job.EquipNum);

                if (_equipValidateService.ValidateStacker(sctag) == false)
                {
                    return IotMsgConst.ScError;
                }

                if (sctag.SC_State == 2 && sctag.ActionType == 2)
                {
                    return IotMsgConst.ScError;
                }
            }









            if (job.JobID2.IsNotNullOrEmpty())
            {
                if (!ScOutJobDic.ContainsKey($"{job.JobID}-{job.JobID2}"))
                {

                    ValidateJob(2, job.EquipNum);

                    var isAdd = ScOutJobDic.TryAdd($"{job.JobID}-{job.JobID2}", job);
                    if (!isAdd)
                    {
                        ScOutJobDic.TryAdd($"{job.JobID}-{job.JobID2}", job);
                    }
                }

            }
            else
            {
                if (!ScOutJobDic.ContainsKey(job.JobID))
                {
                    if (job.ToStation != 999)
                    {
                       
                        ValidateJob(2, job.EquipNum);
                    }
                    var isAdd = ScOutJobDic.TryAdd(job.JobID, job);
                    if (!isAdd)
                    {
                        ScOutJobDic.TryAdd(job.JobID, job);
                    }

                }

            }
        }
        catch   (Exception e)
        {
            return e.Message;
        }
        return string.Empty;


    }

   
    /// <summary>
    /// 移除移库任务
    /// </summary>
    /// <param name="job"></param>
    /// <returns></returns>
    public async Task<bool> RemoveMoveJob(ScMoveJob job)
    {
        string dickey = job.JobID;

        if (ScMoveJobDic.ContainsKey(dickey))
        {
            ScMoveJobDic.TryRemove(dickey, out _);
        }
      



        var sctag = _processDataService.ScUnits.GetValueOrDefault(job.EquipNum);
        if (sctag != null)
        {
            sctag.JobIDOld = sctag.JobID;
            sctag.JobID = String.Empty;
        }
        return true;
    }


    /// <summary>
    /// 移除入库任务
    /// </summary>
    /// <param name="job"></param>
    /// <returns></returns>
    public async Task<bool> RemoveEnterJob(ScEnterJob job)
    {
        string dickey = job.JobID;
        if (job.JobID2.IsNotNullOrEmpty())
        {
            dickey = $"{job.JobID}-{job.JobID2}";

        }
        if (ScEnterJobDic.ContainsKey(dickey))
        {
            ScEnterJobDic.TryRemove(dickey, out _);
        }


        var sctag = _processDataService.ScUnits.GetValueOrDefault(job.EquipNum);
        if (sctag != null)
        {
            sctag.JobIDOld = sctag.JobID;
            sctag.JobID = String.Empty;
        }
        return true;
    }
    /// <summary>
    /// 移除出库任务
    /// </summary>
    /// <param name="job"></param>
    /// <returns></returns>
    public async Task<bool> RemoveOutJob(ScOutJob job)
    {
        string dickey = job.JobID;
        if (job.JobID2.IsNotNullOrEmpty())
        {
            dickey = $"{job.JobID}-{job.JobID2}";

        }
        if (ScOutJobDic.ContainsKey(dickey))
        {
            ScOutJobDic.TryRemove(dickey, out _);
        }



        var sctag = _processDataService.ScUnits.GetValueOrDefault(job.EquipNum);
        if (sctag != null)
        {
            sctag.JobIDOld = sctag.JobID;
            sctag.JobID = String.Empty;
        }
        return true;
    }



    #endregion
}
